package com.ProjetEISD.extraction;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;


import com.sun.cnpi.rss.elements.Channel;
import com.sun.cnpi.rss.elements.Item;
import com.sun.cnpi.rss.elements.PubDate;
import com.sun.cnpi.rss.elements.Rss;
import com.sun.cnpi.rss.parser.RssParser;
import com.sun.cnpi.rss.parser.RssParserFactory;
import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;

import java.io.FilenameFilter;

import javax.swing.text.DateFormatter;

import sun.misc.Regexp;

class RSSFilter implements FilenameFilter {
	public boolean accept(File dir, String name) {
		return (name.endsWith(".xml")|| name.endsWith(".rss"));
	}
}
public class Extractor {

	// vecteur qui va contenir l'ensemble des matchs récupérés dans les flux RSS
	Vector<Match> matches;

	// pourcentage de l'opération
	int pourcentage;

	// dernier match considéré
	Match dernierMatch;

	private final static int DEFAITE=0;
	private final static int NUL=1;
	private final static int VICTOIRE=3;
	private final static int INCONNU=-1;
	// dernier état considéré (0: défaite, 1: match nul, 3: trois points)
	int lastState;
	boolean waitingForGoal;
	boolean waitingForEndofDate;
	int bracketsToClose;
	String lastDate;
	GregorianCalendar daterss;

	public Extractor()
	{
		// initialisation des structures de données
		matches=new Vector<Match>();
		pourcentage=0;
		waitingForGoal=false;
		waitingForEndofDate=false;
		bracketsToClose=0;
		lastDate="";
	}

	// Récupère des informations à partir de tous les fichiers RSS contenus dans le répetoire directory, d'extension extension
	public void processRssFiles(String directory,String extension)
	{
		File dir=new File(directory);
		FilenameFilter f=new RSSFilter();
		File [] fichiers=dir.listFiles(f);
		if (fichiers==null)
		{
			System.out.println("Erreur, pas de fichier rss à analyser (vérifier que c'est le bon répertoire)");
			return;
		}

		for (int i=0; i< fichiers.length; i++)
		{
			File fichierCourant=fichiers[i];
			analyse(fichierCourant);
			pourcentage = (i/fichiers.length)*100;
			System.out.println("Running:"+pourcentage+" % done...");
		}


	}
	private void analyse(File fichierCourant) {
		// chargement du fichier dans le parseur RSS
		try {
			RssParser parser = RssParserFactory.createDefault();
			Rss rss = parser.parse(fichierCourant);
			/* analyse à proprement parler */

			// récupération du Channel
			Channel myfreesport=rss.getChannel();
			// Puisque les RSS ne semblent pas avoir la date essayer de la deviner du nom du fichier
			Pattern pattern=Pattern.compile("(\\d+)_(\\d+)_(\\d+)");
			Matcher m=pattern.matcher(fichierCourant.getName());
			if (m.find())
			{	
				if (fichierCourant.getName().contains("flux")) // fichiers qu'on nous a fournis
					daterss=new GregorianCalendar(2000+Integer.parseInt(m.group(1)),Integer.parseInt(m.group(2)),Integer.parseInt(m.group(3)));
				else
					daterss=new GregorianCalendar(2000+Integer.parseInt(m.group(3)),Integer.parseInt(m.group(2)),Integer.parseInt(m.group(1))); // fichiers qu'on télécharge nous-même
			}
			System.out.println("pubDate="+daterss);
			Vector<Item> items=(Vector<Item>)myfreesport.getItems();
			System.out.println("Info: "+items.size()+" items trouvés dans le RSS");
			for (int i=0;i< items.size();i++)
			{
				// ne garder que la ligue 1
				Item current=items.elementAt(i);
				if (current.getLink().getText().contains("ligue1"))
				{
					// on récupère la description de l'élément
					String description=current.getDescription().getText(); 
					System.out.println("description: "+description);

					// on télécharge l'article associé
					//String htmlPage="";
					URL url=new URL(current.getLink().getText());
					String urlString=current.getLink().getText();
					System.out.println("Téléchargement de l'article associé :"+urlString);


					try
					{

						String commande="run-cass-rule french "+url+" f html/"+url.getFile().substring(url.getFile().lastIndexOf("/")+1)+" /home/nicolas/tmp/scol-1-12/tools";
						System.out.println("lancement de "+commande);
						Process p=Runtime.getRuntime().exec("/bin/sh "+commande);

						p.waitFor();

						//System.out.println("sortie="+outValue);
						String buffer="";
						File f=new File("tmp.cass");
						BufferedReader in = new BufferedReader(new FileReader(f));
						String line="";
						while ((line=in.readLine())!=null)
							buffer += line+"\n";
						System.out.println("taille du buffer lu: "+buffer.length()+ "octets");

						analyseSortieCass(buffer);
						f.delete();

					}
					catch(Exception ex) {  ex.printStackTrace(); }

				}
				else
				{
					System.out.println("pas de ligue1 dans ce tag");
				}
			}

		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	private void analyseSortieCass(String cass) {
		// patterns:
		// date (pour la date)
		// equipe: g gagné p perdu n match nul
		// score: sg score 
		// vainqueur
		// buteur
		System.out.println("analyse du buffer...");
		//System.out.println("<buffer>"+cass+"</cass>");
		Vector<Match> matchsDeLaJournee=new Vector<Match>();

		try{
			dernierMatch=new Match();
			dernierMatch.setDate(daterss);
			// composition des patterns
			Pattern equipe = Pattern.compile("equipe\\s(\\w+|_+)");
			Pattern score = Pattern.compile("num\\s(\\d+)");
			// Pattern gagner= Pattern.compile("gagner");
			//Pattern nul= Pattern.compile("perdre");
			// Pattern marquer= Pattern.compile("marquer");
			Pattern date=Pattern.compile("date|jour|mois");
			Pattern buteur=Pattern.compile("joueur(\\w+|_+)\\s(\\w+|\\-+)");

			StringTokenizer tokenizer=new StringTokenizer(cass,"\n");
			// On essaye de récupérer les équipes, les scores, les joueurs, les dates...
			while (tokenizer.hasMoreTokens())
			{
				String line=tokenizer.nextToken();
				//  System.out.println("token:"+line);

				if (line.contains("equipe"))
				{
					System.out.println("equipe trouvée");
					Matcher m=equipe.matcher(line);
					if (m.find())
					{
						if (dernierMatch.getEquipe1().equals(""))
							dernierMatch.setEquipe1(m.group(1));
						else
							if (dernierMatch.getEquipe2().equals("") && !dernierMatch.getEquipe1().equals(m.group(1)))
							{
								dernierMatch.setEquipe2(m.group(1));

							}
							else if (dernierMatch.getEquipe2()!="")
							{
								matchsDeLaJournee.add(dernierMatch); // à priori pas de nouvelle info sur ce match
								dernierMatch=new Match();
								dernierMatch.setEquipe1(m.group(1));
								lastState=INCONNU;
								System.out.println("match ajouté");
							}
						//}
					}
					else
					{
						System.out.println("impossible de récupérer l'équipe");

					}
					System.out.println("équipe1="+dernierMatch.getEquipe1());
					System.out.println("équipe2="+dernierMatch.getEquipe2());
				}
				else if (line.contains("m="))
				{
					System.out.println("victoire trouvée");
					Matcher m=score.matcher(line);
					if (m.find())
					{
						System.out.println(m.group(1));
						if (m.group(1)==null)
						{
							System.out.println("erreur score="+m.group());
						}
						else
						{
							String scoret=m.group(1);
							int scoref=(Integer.parseInt(scoret));
							if (scoref < 20) // On a rarement vu plus dans l'histoire du football
								dernierMatch.setScoreEquipe1(scoref);
							else
								System.out.println("Warning: this number ("+scoref+") doesn't seem to be a score! Ignoring... ");
						}
					}
					else
					{
						System.out.println("impossible de récupérer le score gagnant");
					}
				}
				else if (line.contains("f="))
				{
					System.out.println("défaite trouvée");
					Matcher m=score.matcher(line);
					if (m.find())
					{
						if (m.group(1)==null)
						{
							System.out.println("erreur score="+m.group());
						}
						else
						{
							String scoret=m.group(1);
							int scoref=(Integer.parseInt(scoret));
							if (scoref < 20) // On a rarement vu plus dans l'histoire du football
								dernierMatch.setScoreEquipe2(scoref);
							else
								System.out.println("Warning: this number ("+scoref+") doesn't seem to be a score! Ignoring... ");
						}

					}
					else
					{
						System.out.println("impossible de récupérer le score perdant");
					}
				}
				else if (line.contains("gagner"))
				{
					System.out.println("gagner trouvé");
					lastState=VICTOIRE;
				}
				else if (line.contains("perdre"))
				{
					System.out.println("perdre trouvé");
					lastState=DEFAITE;
				}
				else if (line.contains("marquer"))
				{
					System.out.println("marquer trouvé");
					waitingForGoal=true;
				}
				else if (line.contains("joueur"))
				{
					System.out.println("joueur trouvé");
					if (!waitingForGoal)
						continue;

					Matcher m=buteur.matcher(line);
					if (m.find())
					{
						String equipeSupposee=m.group(1);
						String nomJoueur=m.group(2);
						System.out.println("joueur considéré="+nomJoueur);
						System.out.println("équipe: "+equipeSupposee);
						System.out.println("équipe 1:"+dernierMatch.getEquipe1());
						System.out.println("équipe 2:"+dernierMatch.getEquipe2());
						if (dernierMatch.getEquipe1().equals(equipeSupposee))
						{
							Vector<String> buteursEquipe1=dernierMatch.getButeursEquipe1();
							buteursEquipe1.add(nomJoueur);
							dernierMatch.setButeursEquipe1(buteursEquipe1);
							waitingForGoal=false;
						}
						else
							if (dernierMatch.getEquipe2().equals(equipeSupposee))
							{
								Vector<String> buteursEquipe2=dernierMatch.getButeursEquipe2();
								buteursEquipe2.add(nomJoueur);
								dernierMatch.setButeursEquipe2(buteursEquipe2);
								waitingForGoal=false;
							}
							else
							{

								for (int i=matchsDeLaJournee.size()-1;i>=0;i--)
								{
									Match m_tmp=matchsDeLaJournee.elementAt(i);
									if (equipeSupposee.equals(m_tmp.getEquipe1()))
									{
										Vector<String> buteurseq1=m_tmp.getButeursEquipe1();
										buteurseq1.add(nomJoueur);
										m_tmp.setButeursEquipe1(buteurseq1);
										matchsDeLaJournee.set(i,m_tmp);
										break;
									}
									else if
									(equipeSupposee.equals(m_tmp.getEquipe2()))
									{
										Vector<String> buteurseq2=m_tmp.getButeursEquipe2();
										buteurseq2.add(nomJoueur);
										m_tmp.setButeursEquipe2(buteurseq2);
										matchsDeLaJournee.set(i,m_tmp);
										break;

									}
								}
							}

					}
					else
					{
						System.out.println("Impossible de récupérer le buteur");
					}

				}
				else
				{
					Matcher m=date.matcher(line);

					if (m.find())
					{

						System.out.println("date trouvée");
						lastDate+=line;
						if (line.contains("]))"))
						{
							parseDate(lastDate);
							lastDate="";
						}
					}
				}
				if (waitingForEndofDate)
				{
					if (line.contains("["))
					{
						bracketsToClose++;
					}
					else if (line.contains("]"))
					{
						bracketsToClose--;
					}
					lastDate+=line;
					if (bracketsToClose==0)
					{
						parseDate(lastDate);
						lastDate="";
					}
				}

			}


		}catch(PatternSyntaxException pse){
			pse.printStackTrace();
		} 
		cleanUp(matchsDeLaJournee);
		//matches.addAll(matchsDeLaJournee);
		matchsDeLaJournee.clear();
		// Calculer les vainqueurs
		for (int i=0;i<matches.size();i++)
		{
			Match m=matches.elementAt(i);

			if (m.getScoreEquipe1() > m.getScoreEquipe2())
			{
				m.setVainqueur(m.getEquipe1());
			}
			else if (m.getScoreEquipe2() > m.getScoreEquipe1())
			{
				m.setVainqueur(m.getEquipe2());
			}
			matches.set(i,m);
		}
	}

	// nettoie les matchs de la journée en éliminant les redondances et les matchs improbables
	private void cleanUp(Vector<Match> match) {
		// nettoyage des doublons
		Vector<Match> matchsDeLaJournee=match;
		System.out.println("Cleanup des matchs...");
		for (int i=0;i<matchsDeLaJournee.size();i++)
		{
			Match doublon=matchsDeLaJournee.elementAt(i);
			for (int j=0;j<matchsDeLaJournee.size();j++)
			{
				if (i==j) continue;
				Match curr=matchsDeLaJournee.elementAt(j);
				if ((doublon.getEquipe1().equals(curr.getEquipe1()) && doublon.getEquipe2().equals(curr.getEquipe2())) || 
						(doublon.getEquipe1().equals(curr.getEquipe2()) && doublon.getEquipe2().equals(curr.getEquipe1())))
				{
					matchsDeLaJournee.remove(j);
					System.out.println("doublon détecté");
				}
			}
		}
		// une équipe ne peut jouer qu'une seule fois
		Vector<String> equipesAyantDejaJoue=new Vector<String>();
		Vector<String> equipesEnSuspens=new Vector<String>();

		for (int i=0;i<matchsDeLaJournee.size();i++)
		{
			Match m=matchsDeLaJournee.elementAt(i);
			String equipe1=m.getEquipe1();
			String equipe2=m.getEquipe2();

			if (equipesAyantDejaJoue.contains(equipe1))
			{
				if (equipesEnSuspens.contains(equipe2))
				{
					equipesEnSuspens.add(equipe2);
				}
				else
				{
					matchsDeLaJournee.remove(i);
				}
			}
			else if (equipesAyantDejaJoue.contains(equipe2))
			{
				if (equipesEnSuspens.contains(equipe1))
				{
					equipesEnSuspens.add(equipe1);
				}
				else
				{
					matchsDeLaJournee.remove(i);
				}
			}
			else
			{
				equipesAyantDejaJoue.add(equipe1);
				equipesAyantDejaJoue.add(equipe2);
			}
		}
		if (equipesEnSuspens.size()%2==0)
		{
			for (int i=0;i<equipesEnSuspens.size();i+=2)
			{
				String equipe1=equipesEnSuspens.elementAt(i);
				String equipe2=equipesEnSuspens.elementAt(i+1);
				Match m=new Match();
				m.setEquipe1(equipe1);
				m.setEquipe2(equipe2);
				m.setDate(daterss);
				matchsDeLaJournee.add(m);
			}
		}
		// Correction des dates et des scores
		for (int i=0;i<matchsDeLaJournee.size();i++)
		{
			Match courant=matchsDeLaJournee.elementAt(i);
			GregorianCalendar d=courant.getDate();

			if (d!=null)
			{
				int months=d.get(d.MONTH);
				if (d.get(d.YEAR)!=2007 && d.get(d.YEAR)!=2008)
				{

					if (months<8)
					{
						d.set(d.YEAR,2008);
					}
					else
						d.set(d.YEAR,2007);

				}

				if (months==0)
				{
					months=1;
					d.set(d.MONTH,months);
				}
				int days=d.get(d.DAY_OF_MONTH);
				if (days==0)
					d.set(d.DAY_OF_MONTH,days);



				courant.setDate(d);
			}
			// correction des buteurs
			int score1=courant.getScoreEquipe1();
			int score2=courant.getScoreEquipe2();
			Vector<String> buteurs1=courant.getButeursEquipe1();
			Vector<String> buteurs2=courant.getButeursEquipe2();
			if (score1<buteurs1.size())
				score1=buteurs1.size();
			if (score2<buteurs2.size())
				score2=buteurs2.size();
			courant.setScoreEquipe1(score1);
			courant.setScoreEquipe2(score2);
			matchsDeLaJournee.set(i, courant);
		}





		matches.addAll(matchsDeLaJournee);
	}

	// Analyse la date extraite par cass et la met au format JJ/MM/AAAA pour la base de données
	private void parseDate(String date) {
		String [] mois={"janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"};
		String [] jours={"dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"};
		java.util.Hashtable<String, Integer > hashMois=new java.util.Hashtable<String, Integer>();
		java.util.Hashtable<String, Integer > hashJour=new java.util.Hashtable<String, Integer>();
		for (int i=0;i<mois.length;i++)
		{
			hashMois.put(mois[i],i);
		}
		for (int i=0;i<jours.length;i++)
		{
			hashJour.put(jours[i], i);
		}
		Vector<Pattern> patterns=new Vector<Pattern>();
		Pattern dc1=Pattern.compile("(jour.*)?num\\s+(\\d+).*(mois\\s+(\\w+))?(num\\s+(\\d+))?");
		patterns.add(dc1);
		Pattern dc2=Pattern.compile("(jour.*)num\\s+(\\d+)(.*)(mois\\s+(\\w+))?");
		patterns.add(dc2);
		Pattern dc3=Pattern.compile("aujourd'hui");
		patterns.add(dc3);
		Pattern dc4=Pattern.compile("hier");
		patterns.add(dc4);
		Pattern dc5=Pattern.compile("avant-hier");
		patterns.add(dc5);
		Pattern dc6=Pattern.compile("lundi|mardi|mercredi|jeudi|vendredi|samedi|dimanche");
		patterns.add(dc6);
		GregorianCalendar d=daterss;
		for (int i=0;i<patterns.size();i++)
		{
			Pattern curr=patterns.elementAt(i);
			Matcher m=curr.matcher(date);
			if (m.find())
			{
				System.out.println("pattern dc"+(i+1));
				switch (i)
				{
				case 0:

					d.set(d.DATE,new Integer(m.group(2)).intValue());
					d.set(d.MONTH,hashMois.get(m.group(5)));
					d.set(d.YEAR,new Integer(m.group(6)));
					dernierMatch.setDate(d);
					break;
				case 1:

					d.set(d.DATE,new Integer(m.group(2)).intValue());
					d.set(d.MONTH,hashMois.get(m.group(5)));
					dernierMatch.setDate(d);
					//d.setYear(new Integer(m.group(6)));
					break;
				case 2:
					//d=new Date(daterss.toString());
					dernierMatch.setDate(daterss);
					break;
				case 3:

					d.set(d.DATE,d.DATE-1);
					dernierMatch.setDate(d);
					break;
				case 4:
					d.set(d.DATE,d.DATE-2);
					dernierMatch.setDate(d);
					break;
				case 5:
					d.set(d.DAY_OF_WEEK, hashJour.get(m.group()));
					dernierMatch.setDate(d);
				default:
					break;
				}
			}

		}

	}

	public Vector<Match> getMatches() {
		return matches;
	}

	public int getPourcentage() {
		return pourcentage;
	}

	public static void main(String[] args)
	{
		Extractor ex=new Extractor();
		//ex.processRssFiles("rss", ".xml");
		ex.analyse(new File("rss/rss24_2_08.xml"));
		Vector<Match> matchs=ex.getMatches();
		for (int i=0;i<matchs.size();i++)
		{
			System.out.println(matchs.elementAt(i));
		}

	}



}
